package it.disim.tlp.webreputation.threading;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.swing.text.html.CSS;

import it.disim.tlp.webreputation.aggregatorplugin.AggregatorPlugin;
import it.disim.tlp.webreputation.aggregatorplugin.AggregatorPost;
import it.disim.tlp.webreputation.aggregatorplugin.ManifestLoader;
import it.disim.tlp.webreputation.aggregatorplugin.ManifestedPlugin;
import it.disim.tlp.webreputation.business.AbstractDataAggregatorFactory;
import it.disim.tlp.webreputation.business.ConnectorService;
import it.disim.tlp.webreputation.business.FactoryBuilder;
import it.disim.tlp.webreputation.business.PostService;
import it.disim.tlp.webreputation.business.SorgenteService;
import it.disim.tlp.webreputation.business.model.Connector;
import it.disim.tlp.webreputation.business.model.Post;
import it.disim.tlp.webreputation.business.model.Sorgente;
import it.disim.tlp.webreputation.business.model.Topic;
import it.disim.tlp.webreputation.exceptions.AggregatorLogger;
import it.disim.tlp.webreputation.exceptions.QuotaExceededException;
import it.disim.tlp.webreputation.simulation.SentimentAnalyzer;
import it.disim.tlp.webreputation.simulation.TopicExtractor;

public class AggregatorThread extends Thread {
	private AbstractDataAggregatorFactory factory;
	private AggregatorPlugin ap;
	private ManifestLoader ml;
	private Connector c;
	private Collection<Sorgente> sorgenti;
	
	/**
	 * This constructor creates a new Thread for a plugin by passing its loaded
	 * interface, Manifest and related Connector.
	 * @param ap Plugin Interface.
	 * @param ml Plugin ManifestLoader.
	 * @param c Connector c.
	 */
	public AggregatorThread(AggregatorPlugin ap,ManifestLoader ml, Connector c ){
		this.ap = ap;
		this.ml = ml;
		this.c = c;
		this.factory = FactoryBuilder.getInstance();
	}
	
	public void run(){
		while(true){
			try {
				System.out.println("Waiting for plugin "+ml.getName()+"... "+c.getUpdateInterval()+" minutes.");
				
				sleep(((long)c.getUpdateInterval()*60000));
			} catch (InterruptedException e) {
				break;
			}
			System.out.println("Executing plugin " +ml.getName()+"...");
			
			ConnectorService cs = factory.getConnectorService();
			c = cs.getConnector(c); /* sources refreshing*/
			this.sorgenti = c.getSorgenti();
			
			for(Sorgente s : sorgenti){
				Date lastTime = new Date(s.getLast_timestamp());
				System.out.println("getting posts from source "+s.getLink()+" starting by "+lastTime+" with plugin "+ml.getName()+"...");
				try{
					List<AggregatorPost> posts = ap.getPosts(s.getLink(), lastTime);
					for(AggregatorPost p : posts){
						double polarity = SentimentAnalyzer.getPolarity(p.getText());
						String[] rawTopics = TopicExtractor.getTopics(p.getText());
						
						/*save post... the underlying backend cares about topics*/
						Collection<Topic> topics = new ArrayList<Topic>();
						for(String rt : rawTopics){
							Topic t = new Topic();
							t.setTopic(rt);
							topics.add(t);
						}
						PostService ps = factory.getPostService();
						Post sPost = new Post(s.getLink(),p.getDate(),String.valueOf(polarity),p.getText(),s,topics);
						ps.savePost(sPost);
					}
					/*source last timestamp updating... problem db TYPE!*/
					Date now = new Date();
					s.setLast_timestamp(now.getTime());
					SorgenteService sc = factory.getSorgenteService();
					System.out.println("updating source "+s.getLink()+" last time to "+now);
					sc.updateSorgente(s);
					
				} catch(QuotaExceededException q){
					System.out.println("Plugin "+ml.getJarName()+" has reached its maximum quota whit this message: "+q.getError()+"... check log file inside logs directory");
					AggregatorLogger.logging(ml.getName(), q);
				}catch(Exception e){
					System.out.println("Errors during plugin "+ml.getName()+" execution retriving from resource "+s.getLink()+" check log file inside logs directory.");
					AggregatorLogger.logging(ml.getName(), e);
				}
			}
			
		}
	}
	
	/**
	 * this method returns the related aggregatorPlugin.
	 * @return AggregatorPlugin ap.
	 */
	public AggregatorPlugin getAggregatorPlugin(){
		return ap;
	}
	
	/**
	 * this method returns the related ManifestLoader.
	 * @return MaifestLoader ml.
	 */
	public ManifestLoader getManifestLoder(){
		return ml; 
	}
	
	/**
	 * this method returns the related Connector.
	 * @return Connector c.
	 */
	public Connector getConnector(){
		return c;
	}
}
